package com.huiquan.symptom.job;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.huiquan.analysis.utils.ListUtil;
import com.huiquan.foundation.util.BusinessUtil;
import com.huiquan.framework.utils.EMailUtil;
import com.huiquan.framework.utils.FileUtils;
import com.huiquan.symptom.dao.SymptomDao;
import com.huiquan.vocab.service.VocabDyadSymptomService;

@Component
public class SymptomJob {

	private static final Logger LOG = LoggerFactory.getLogger(SymptomJob.class);

	@Autowired
	private SymptomDao symptomDao;
	@Autowired
	private EMailUtil eMailUtil;
	@Autowired
	private VocabDyadSymptomService vocabDyadSymptomService;

	/**
	 * 从症状大词同步数据到症状黑名单待校验
	 */
	public void updateMisSymptom() {
		LOG.info("Symptom job update mis symptom begin!");

		symptomDao.initList();

		LOG.info("Symptom job update mis symptom end!");
	}

	@Value("${symptom.reveal.synonym.init.script}")
	private String symptomRevealSynonymInitScript;

	/**
	 * 导入症状展现词同义词
	 * 
	 * @throws Exception
	 */
	public void importSymptomRevealSynonym() throws Exception {
		LOG.info("导入症状展现词同义词数据开始");
		BusinessUtil.excuteShell(new String[] { symptomRevealSynonymInitScript });
		List<String> repeatList = symptomDao.selectRepeatSynonym();

		// 如果有重复数据，则邮件报错，导入终止
		if (!ListUtil.isEmpty(repeatList)) {
			LOG.error("症状展现词同义词有重复数据");
			StringBuilder content = new StringBuilder("重复数据的std为:\n");
			for (String s : repeatList) {
				content.append(s).append("\n");
			}
			List<String> address = new ArrayList<>();
			address.add("xl@witspring.com");
			address.add("wangzhen@witspring.com");
			eMailUtil.sendBatchEmail(content.toString(), "症状展现词同义词有重复数据", address);
			return;
		}

		// 清空未校验展现词语
		symptomDao.deleteNoLabelRevealData();

		// 删除同义词表中与临时表冲突的部分
		symptomDao.deleteRevealSynonymWithTemp();

		// 将临时表中新增的数据添加到同义词表
		symptomDao.insertRevealSynonymWithTemp();

		// 将临时表中新增的数据添加到展现词表
		symptomDao.insertRevealWithTemp();

		// 将临时表中的症状标准词分词维护到展现词表中
		symptomDao.updateStdArrayWithTemp();

		// 将未标记展现词数据中展现词包含“左”、“右”的数据，状态标记为其他(3)
		symptomDao.updateRevealNoLabelStatusToOther();

		// 将未标记展现词数据与同义词最高频一致的部分置为已校验
		symptomDao.updateRevealNoLabelStatusWithSynonym();

		// 这两种情况，未校验可以批量改为已校验: 1. 展现词包含“单侧”; 2. 频数最高的同义词包含‘左’、‘右’、‘双’，展现词不包括这类词。
		symptomDao.batchUpdateRevealStatus();
	}

	@Value("${symptom.reveal.std.array.path}")
	private String revealStdArrayPath;
	@Value("${symptom.reveal.std.array.script}")
	private String revealStdArrayScript;

	/**
	 * 初始化展现词中的当前标准词
	 */
	public void initRevealStdCurrent() throws Exception {
		LOG.info("初始化展现词中的当前标准词开始");

		// 将文件通过元素和二元组标准化症状
		initRevealNewStd();
		LOG.info("将文件通过元素和二元组标准化症状结束");

		// 将标准化症状导入mysql并更改展现词中当前症状
		BusinessUtil.excuteShell(new String[] { revealStdArrayScript });
		LOG.info("将标准化症状导入mysql并更改展现词中当前症状结束");
	}

	private void initRevealNewStd() throws Exception {
		// 获取导出路径
		String filePath = BusinessUtil.getCompletePath4Properties(revealStdArrayPath);

		// 导出数据
		List<Map<String, String>> revealList = symptomDao.retrieveRevealStdArrayList();
		StringBuffer sb = new StringBuffer();
		for (Map<String, String> reveal : revealList) {
			sb.append(reveal.get("symptom_std"));
			sb.append((char) 1);
			sb.append(reveal.get("std_array"));
			sb.append((char) 1);
			sb.append(reveal.get("std_prop"));
			sb.append((char) 1);
			sb.append(1);
			sb.append("\n");
		}

		FileUtils.generateFile(filePath, sb.toString());
		LOG.info("输出所有的展现词的分词到文件结束");

		// 调用方法将该文件转换成标准症状
		vocabDyadSymptomService.localGetSymptomStdDyadByBatch(filePath, "4");
	}

}
